<?php
defined( 'BASEPATH' ) or exit( 'No direct script access allowed' );
class MysqlBackup
{
    private $error;
    private $_db = null;
    private $path;
    function __construct($path = '')
    {
        $this->_db = MyPDO::get_instance();
        $this->path = $path;
    }
    /**
     * 获取指定表的sql转储字符串
     *
     * @param unknown $table_name            
     * @return string
     */
    private function dump_table($table_name)
    {
        $result = "\r\n";
        // 备份表结构
        if ($ddl = $this->_db->query( "SHOW CREATE TABLE `{$table_name}`" )->fetch_row())
        {
            $result .= "/* Table structure for table `{$table_name}` */\r\n";
            $result .= "DROP TABLE IF EXISTS `{$table_name}`;\r\n";
            $result .= $ddl['Create Table'] . ";\r\n\r\n";
        }
        else
        {
            $this->error = "备份表结构（{$table_name}）出错!";
            return '';
        }
        // 备份表数据
        $data = $this->_db->query( "SELECT * FROM `{$table_name}`" )->fetch_all();
        if ($data !== false)
        {
            $result .= "/* Data for the table `{$table_name}` */\r\n";
            if (empty( $data ))
            {
                return $result;
            }
            $columns = '`' . implode( '`,`', array_keys( current( $data ) ) ) . '`';
            foreach ( $data as $row )
            {
                $insert_value = '';
                foreach ( $row as $value )
                {
                    if (is_string( $value ))
                    {
                        $insert_value .= "'" . addcslashes( $value, "'\\\t\r\n" ) . "',";
                        continue;
                    }
                    if (is_null( $value ))
                    {
                        $insert_value .= "NULL,";
                        continue;
                    }
                    $insert_value .= "{$value},";
                }
                $insert_value = substr( $insert_value, 0, - 1 );
                $result .= "INSERT INTO `{$table_name}` ({$columns}) VALUES ({$insert_value});\r\n";
            }
        }
        else
        {
            $this->error = "备份表数据（{$table_name}）出错!";
            return '';
        }
        return $result;
    }
    /**
     * 备份数据到文件
     *
     * @param unknown $backup_name            
     * @param unknown $tables            
     * @return boolean
     */
    function create($backup_name)
    {
        if (empty( $backup_name ))
        {
            $this->error = '备份名称不能为空!';
            return false;
        }
        
        $database = $this->_db->query( 'SELECT DATABASE()' )->fetch_cell();
        $date = date( 'Y-m-d H:i:s', $_SERVER['REQUEST_TIME'] );
        $sql = "/*\r\n";
        $sql .= "MySQL Database Backup Tools\r\n";
        $sql .= "Database : {$database}\r\n";
        $sql .= "Date : {$date}\r\n";
        $sql .= "*/\r\n\r\n";
        $sql .= "SET FOREIGN_KEY_CHECKS=0;\r\n";
        
        $tables = $this->_db->query( 'SHOW TABLES' )->fetch_all();
        if (empty( $tables ))
        {
            $this->error = '数据库中没有表!';
            return false;
        }
        foreach ( $tables as $item )
        {
            $sql .= $this->dump_table( $item["Tables_in_{$database}"] );
            if (! empty( $this->error ))
            {
                return false;
            }
        }
        
        $file = $this->path . $backup_name;
        if (DIRECTORY_SEPARATOR == '\\')
        {
            $file = iconv( 'UTF-8', 'GB2312', $file );
        }
        if (! is_dir( $this->path ) or ! is_really_writable( $this->path ))
        {
            $this->error = '无法创建文件!';
            return;
        }
        if (file_exists( $file ))
        {
            $this->error = '该名称的备份已存在!';
            return;
        }
        file_put_contents( $file, $sql );
        return true;
    }
    /**
     * 从备份文件恢复数据库
     *
     * @param unknown $backup_name            
     * @return boolean
     */
    public function restore($backup_name)
    {
        if (empty( $backup_name ))
        {
            $this->error = '备份名称不能为空!';
            return false;
        }
        $file = $this->path . $backup_name;
        if (DIRECTORY_SEPARATOR == '\\')
        {
            $file = iconv( 'UTF-8', 'GB2312', $file );
        }
        if (! is_file( $file ))
        {
            $this->error = '备份文件不存在!';
            return false;
        }
        $sql_str = file_get_contents( $file );
        $sql_array = explode( ";\r\n", $sql_str );
        foreach ( $sql_array as $sql )
        {
            $sql = str_replace( array (
                    "\r\n",
                    "\r",
                    "\n",
                    "\t" 
            ), '', $sql );
            $sql = preg_replace( '/\/\*.*?\*\//', '', $sql );
            if (empty( $sql ))
            {
                continue;
            }
            if (false === $this->_db->exec( $sql )->execute())
            {
                $this->error = "“{$sql}”语法错误!";
                return false;
            }
        }
        return true;
    }
    /**
     * 错误信息
     *
     * @return mixed
     */
    public function get_error()
    {
        return $this->error;
    }
}
